package cn.gan.loveofsoul.service.impl;

import cn.gan.loveofsoul.commons.result.ConfigContents;
import cn.gan.loveofsoul.commons.result.ErrorMessage;
import cn.gan.loveofsoul.commons.result.Result;
import cn.gan.loveofsoul.commons.result.StatusCode;
import cn.gan.loveofsoul.commons.utils.RedisUtil;
import cn.gan.loveofsoul.entity.CommemorateDay;
import cn.gan.loveofsoul.entity.Relationship;
import cn.gan.loveofsoul.entity.SysConfig;
import cn.gan.loveofsoul.entity.User;
import cn.gan.loveofsoul.entity.constants.StatusEnum;
import cn.gan.loveofsoul.entity.vo.UserVO;
import cn.gan.loveofsoul.exception.BusinessException;
import cn.gan.loveofsoul.mapper.RelationshipMapper;
import cn.gan.loveofsoul.service.ICommemorateDayService;
import cn.gan.loveofsoul.service.IRelationshipService;
import cn.gan.loveofsoul.service.ISysConfigService;
import cn.gan.loveofsoul.service.IUserService;
import cn.hutool.core.map.MapUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ganwh
 * @since 2023-10-26
 */
@Service
public class RelationshipServiceImpl extends ServiceImpl<RelationshipMapper, Relationship> implements IRelationshipService {
    @Autowired
    private IUserService userService;
    @Autowired
    private ISysConfigService sysConfigService;
    @Autowired
    private ICommemorateDayService iCommemorateDayService;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 功能描述: 绑定情侣关系
     *
     * @param targetUserId  邀请绑定用户
     * @param currentUserId 当前接受绑定用户
     * @return cn.gan.loveofsoul.commons.result.Result
     * @author ganwh 2023/10/31 15:23
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result binding(Integer targetUserId, Integer currentUserId) {
        if (targetUserId.equals(currentUserId)) {
            throw new BusinessException(StatusCode.BAD_REQUEST, "不可以绑定自己哦~");
        }

        Result result;
        // 邀请绑定用户信息查询
        Optional<User> targetUserOptional = userService.getOptById(targetUserId);
        targetUserOptional.orElseThrow(() ->
                new BusinessException(StatusCode.NOT_FOUND, ErrorMessage.INVITATION_USER_NOT_EXIST));

        // 当前接受绑定用户信息查询
        Optional<User> currentUserOptional = userService.getOptById(currentUserId);
        currentUserOptional.orElseThrow(() ->
                new BusinessException(StatusCode.NOT_FOUND, ErrorMessage.USER_NOT_EXIST));

        // 查询双方是否已经绑定
        LambdaQueryWrapper<Relationship> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Relationship::getOneUserId, targetUserId).eq(Relationship::getTwoUserId, currentUserId);
        wrapper.or();
        wrapper.eq(Relationship::getTwoUserId, targetUserId).eq(Relationship::getOneUserId, currentUserId);
        Relationship relationship = getOne(wrapper);
        if (Objects.isNull(relationship)) { // 双方未绑定

            // 查询对方是否已经绑定
            Relationship targetRelationship = queryUserRelationship(targetUserId);
            if (Objects.nonNull(targetRelationship)) {
                throw new BusinessException(StatusCode.CONFLICT, "对方" + ErrorMessage.RELATIONSHIP_HAS_BEEN_BOUND);
            }

            // 查询自己是否已经绑定
            Relationship currentRelationship = queryUserRelationship(currentUserId);
            if (Objects.nonNull(currentRelationship)) {
                throw new BusinessException(StatusCode.CONFLICT, "您的" + ErrorMessage.RELATIONSHIP_HAS_BEEN_BOUND);
            }

            // 均未绑定，新建绑定关系
            relationship = new Relationship();
            relationship.setOneUserId(targetUserId);
            relationship.setTwoUserId(currentUserId);
            relationship.setCreateTime(LocalDateTime.now());
            save(relationship);

            // 情侣关系绑定成功，初始化纪念日 --- start
            LambdaQueryWrapper<SysConfig> sysConfigWrapper = new LambdaQueryWrapper<>();
            sysConfigWrapper.eq(SysConfig::getCfgKey, ConfigContents.SysConfigKey.USER_CONFIG);
            sysConfigWrapper.eq(SysConfig::getCfgType, ConfigContents.SysConfigType.COMMEMORATE_DAY);
            sysConfigWrapper.eq(SysConfig::getStatus, StatusEnum.NORMAL.getCode());
            List<SysConfig> sysConfigList = sysConfigService.list(sysConfigWrapper);

            Relationship finalRelationship = relationship;
            List<CommemorateDay> insertCommemorateDayList = new ArrayList<>();
            sysConfigList.forEach(sysConfig -> {
                CommemorateDay commemorateDay = new CommemorateDay();
                commemorateDay.setRelationshipId(finalRelationship.getId());
                commemorateDay.setType(sysConfig.getCfgValue());
                commemorateDay.setCreateTime(LocalDateTime.now());
                commemorateDay.setRemark(sysConfig.getRemark());

                switch (sysConfig.getCfgValue()) {
                    case ConfigContents.CommemorateDayType.TOGETHER_DAY:
                        commemorateDay.setOrder(0);
                        break;
                    case ConfigContents.CommemorateDayType.BIRTHDAY:
                        commemorateDay.setUserId(currentUserId);
                        commemorateDay.setOrder(1);

                        CommemorateDay _commemorateDay = new CommemorateDay();
                        _commemorateDay.setRelationshipId(finalRelationship.getId());
                        _commemorateDay.setType(sysConfig.getCfgValue());
                        _commemorateDay.setCreateTime(LocalDateTime.now());
                        _commemorateDay.setUserId(targetUserId);
                        _commemorateDay.setOrder(2);
                        insertCommemorateDayList.add(_commemorateDay);
                        break;
                    case ConfigContents.CommemorateDayType.WEDDING_DAY:
                        commemorateDay.setOrder(3);
                        break;
                    default:
                        commemorateDay.setOrder(insertCommemorateDayList.size() + 3);
                        break;
                }
                insertCommemorateDayList.add(commemorateDay);
            });
            iCommemorateDayService.saveBatch(insertCommemorateDayList);
            // 情侣关系绑定成功，初始化纪念日 --- end
        }

        // 绑定成功，清除缓存
        String targetKey = DigestUtil.md5Hex(String.valueOf(targetUserId));
        String currentKey = DigestUtil.md5Hex(String.valueOf(currentUserId));
        redisUtil.del(ConfigContents.INITIATING_BINDING_REDIS_KEY_PREFIX + targetKey,
                ConfigContents.INITIATING_BINDING_REDIS_KEY_PREFIX + currentKey);

        result = new Result(StatusCode.SUCCESS, ErrorMessage.RELATIONSHIP_BOUND_SUCCESS);
        return result;
    }

    /**
     * 功能描述: 获取情侣关系
     *
     * @param userId
     * @return cn.gan.loveofsoul.commons.result.Result
     * @author ganwh 2023/11/1 10:48
     */
    @Override
    public Result queryRelationship(Integer userId) {
        Relationship relationship = queryUserRelationship(userId);
        if (Objects.isNull(relationship)) {
            throw new BusinessException(StatusCode.NOT_FOUND, ErrorMessage.HAS_NO_RELATIONSHIP);
        }
        Integer lovesUserId;
        if (relationship.getOneUserId().equals(userId)) {
            lovesUserId = relationship.getTwoUserId();
        } else {
            lovesUserId = relationship.getOneUserId();
        }

        LambdaQueryWrapper<CommemorateDay> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CommemorateDay::getRelationshipId, relationship.getId());
        wrapper.eq(CommemorateDay::getType, ConfigContents.CommemorateDayType.TOGETHER_DAY);
        CommemorateDay commemorateDay = iCommemorateDayService.getOne(wrapper);

        Optional<User> lovesUserOptional = userService.getOptById(lovesUserId);
        lovesUserOptional.orElseThrow(() ->
                new BusinessException(StatusCode.NOT_FOUND, ErrorMessage.INVITATION_USER_NOT_EXIST));

        UserVO lovesUserVO = User.convert2UserVO(lovesUserOptional.get());
        Map<String, Object> resultMap = MapUtil.newHashMap();
        resultMap.put("lovesUser", lovesUserVO);
        resultMap.put("relationship", relationship);
        resultMap.put("togetherDay", commemorateDay);
        return new Result(StatusCode.SUCCESS, ErrorMessage.SUCCESS, resultMap);
    }

    /**
     * 功能描述: 获取用户的情侣关系
     *
     * @param userId
     * @return cn.gan.loveofsoul.entity.Relationship
     * @author ganwh 2023/11/1 10:34
     */
    public Relationship queryUserRelationship(Integer userId) {
        LambdaQueryWrapper<Relationship> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Relationship::getOneUserId, userId);
        wrapper.or().eq(Relationship::getTwoUserId, userId);
        return getOne(wrapper);
    }
}
